/*  SSEBPanelController.m
 *  MESLib
 * 
 * Copyright 2003-2009 Starline Software Ltd
 * 
 * This file is part of MESLib.
 * 
 * MESLib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MESLib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with MESLib. If not, see <http://www.gnu.org/licenses/>.
 */
//  Created by Tobias Haughton on Wed Apr 16 2003.
//

#import "SSEBPanelController.h"
#import "SSCatalystDocument.h"


@implementation SSEBPanelController

+ (id)sharedEBPanelController {
   static SSEBPanelController *ebPanelController = nil;

   if(!ebPanelController) {
      ebPanelController = [[SSEBPanelController allocWithZone:[self zone]] init];
   }
   return ebPanelController;
}

- (id)init {
   if(floor(NSAppKitVersionNumber) >= 743) {
      isUsing103OrLater = YES;
      self = [super initWithWindowNibName:@"EBPanel"];
   } else {
      //in 10.2
      isUsing103OrLater = NO;
      self = [super initWithWindowNibName:@"EBPanelPre103"];
   }
   
   if (self) {
      [self setWindowFrameAutosaveName:@"EBPanel"];
      NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
      [nc addObserver:self
             selector:@selector(reload)
                 name:@"SSActorChanged"
               object:nil];
      [nc addObserver:self
             selector:@selector(reload)
                 name:@"SSActionChanged"
               object:nil];
      [nc addObserver:self
             selector:@selector(reload)
                 name:@"SSLocationChanged"
               object:nil];
      [nc addObserver:self
             selector:@selector(reload)
                 name:@"SSSourceChanged"
               object:nil];
      [nc addObserver:self
             selector:@selector(reload)
                 name:@"SSObjectChanged"
               object:nil];
      [nc addObserver:self
             selector:@selector(setNeedsUpdate)
                 name:@"SSEventAddedToDocument"
               object:nil];
      [nc addObserver:self
             selector:@selector(updateTableDisplay:)
                 name:@"SSEBTableDisplayChanged"
               object:nil];
      [nc addObserver:self
             selector:@selector(reload)
                 name:@"SSUpdateAuxiliaryPanels"
               object:nil];

      unusedTableColumns = [[NSMutableArray alloc] init];
   }
   return self;
}

- (void)awakeFromNib
{
   [self setupTable];
   
   //create the search menu
   NSMenu *cellMenu = [[NSMenu alloc] initWithTitle:@"Panel Search"];
   NSMenuItem *titleItem, *allFieldsItem, *actorItem, *actionItem, *objectItem, *locationItem, *sourceItem, *remarkItem, *beginDateItem, *beginTimeItem, *endDateItem, *endTimeItem;
   id searchCell = [searchField cell];
   
   titleItem = [[NSMenuItem alloc] initWithTitle:@"Search In:" action:NULL keyEquivalent:@""]; 
   [cellMenu insertItem:titleItem atIndex:0]; 
   [titleItem release]; 

   allFieldsItem = [[NSMenuItem alloc] initWithTitle:@"All Columns" action:@selector(searchTypeChanged:) keyEquivalent:@""]; 
   [allFieldsItem setState:NSOnState];
   [allFieldsItem setTag:SSEBSearchAllType];
   [cellMenu insertItem:allFieldsItem atIndex:1]; 
   [allFieldsItem release]; 
   
   actorItem = [[NSMenuItem alloc] initWithTitle:@"Actor" action:@selector(searchTypeChanged:) keyEquivalent:@""]; 
   [actorItem setTag:SSEBSearchActorType];
   [cellMenu insertItem:actorItem atIndex:2]; 
   [actorItem release]; 
   
   actionItem = [[NSMenuItem alloc] initWithTitle:@"Action" action:@selector(searchTypeChanged:) keyEquivalent:@""]; 
   [actionItem setTag:SSEBSearchActionType];
   [cellMenu insertItem:actionItem atIndex:3]; 
   [actionItem release]; 
   
   objectItem = [[NSMenuItem alloc] initWithTitle:@"Object" action:@selector(searchTypeChanged:) keyEquivalent:@""]; 
   [objectItem setTag:SSEBSearchObjectType];
   [cellMenu insertItem:objectItem atIndex:4]; 
   [objectItem release]; 
   
   locationItem = [[NSMenuItem alloc] initWithTitle:@"Location" action:@selector(searchTypeChanged:) keyEquivalent:@""]; 
   [locationItem setTag:SSEBSearchLocationType];
   [cellMenu insertItem:locationItem atIndex:5]; 
   [locationItem release]; 
   
   sourceItem = [[NSMenuItem alloc] initWithTitle:@"Source" action:@selector(searchTypeChanged:) keyEquivalent:@""]; 
   [sourceItem setTag:SSEBSearchSourceType];
   [cellMenu insertItem:sourceItem atIndex:6]; 
   [sourceItem release]; 
   
   remarkItem = [[NSMenuItem alloc] initWithTitle:@"Remark" action:@selector(searchTypeChanged:) keyEquivalent:@""]; 
   [remarkItem setTag:SSEBSearchRemarkType];
   [cellMenu insertItem:remarkItem atIndex:7]; 
   [remarkItem release]; 
   
   beginDateItem = [[NSMenuItem alloc] initWithTitle:@"Begin Date" action:@selector(searchTypeChanged:) keyEquivalent:@""]; 
   [beginDateItem setTag:SSEBSearchBeginDateType];
   [cellMenu insertItem:beginDateItem atIndex:8]; 
   [beginDateItem release]; 
   
   beginTimeItem = [[NSMenuItem alloc] initWithTitle:@"Begin Time" action:@selector(searchTypeChanged:) keyEquivalent:@""]; 
   [beginTimeItem setTag:SSEBSearchBeginTimeType];
   [cellMenu insertItem:beginTimeItem atIndex:9]; 
   [beginTimeItem release]; 
   
   endDateItem = [[NSMenuItem alloc] initWithTitle:@"End Date" action:@selector(searchTypeChanged:) keyEquivalent:@""]; 
   [endDateItem setTag:SSEBSearchEndDateType];
   [cellMenu insertItem:endDateItem atIndex:10]; 
   [endDateItem release]; 
   
   endTimeItem = [[NSMenuItem alloc] initWithTitle:@"End Time" action:@selector(searchTypeChanged:) keyEquivalent:@""]; 
   [endTimeItem setTag:SSEBSearchEndTimeType];
   [cellMenu insertItem:endTimeItem atIndex:11]; 
   [endTimeItem release]; 
   
   [searchCell setSearchMenuTemplate:cellMenu];
}

- (void)setMainWindow:(NSWindow *)mainWindow {
   needsUpdate = YES;
}

- (void)setupTable
{
   NSPopUpButtonCell *buttonCell = [[[NSPopUpButtonCell alloc] initTextCell:NSLocalizedString(@"White", nil) pullsDown:NO] autorelease];
   [[buttonCell itemAtIndex:0] setTag:SSWhiteLabelType];
   [buttonCell setControlSize:NSSmallControlSize];

   [buttonCell insertItemWithTitle:NSLocalizedString(@"Yellow", nil) atIndex:[buttonCell numberOfItems]];
   [[buttonCell itemAtIndex:1] setTag:SSYellowLabelType];
   [buttonCell insertItemWithTitle:NSLocalizedString(@"Green", nil) atIndex:[buttonCell numberOfItems]];
   [[buttonCell itemAtIndex:2] setTag:SSGreenLabelType];
   [buttonCell insertItemWithTitle:NSLocalizedString(@"LightBlue", nil) atIndex:[buttonCell numberOfItems]];
   [[buttonCell itemAtIndex:3] setTag:SSLightBlueLabelType];
   [buttonCell insertItemWithTitle:NSLocalizedString(@"Blue", nil) atIndex:[buttonCell numberOfItems]];
   [[buttonCell itemAtIndex:4] setTag:SSBlueLabelType];
   [buttonCell insertItemWithTitle:NSLocalizedString(@"Purple", nil) atIndex:[buttonCell numberOfItems]];
   [[buttonCell itemAtIndex:5] setTag:SSPurpleLabelType];
   [buttonCell insertItemWithTitle:NSLocalizedString(@"Orange", nil) atIndex:[buttonCell numberOfItems]];
   [[buttonCell itemAtIndex:6] setTag:SSOrangeLabelType];
   [buttonCell insertItemWithTitle:NSLocalizedString(@"Red", nil) atIndex:[buttonCell numberOfItems]];
   [[buttonCell itemAtIndex:7] setTag:SSRedLabelType];

   [[tableView tableColumnWithIdentifier:@"label"] setDataCell:buttonCell];

   NSEnumerator *enumerator = [[tableView tableColumns] objectEnumerator];
   id anObject;

   while (anObject = [enumerator nextObject]) {
      //change the font for each of the columns
      [[anObject dataCell] setFont:[NSFont fontWithName:@"Helvetica" size:10]];
   }
      
   [[[tableView tableColumnWithIdentifier:@"actor"] dataCell] setWraps:YES];
   [[[tableView tableColumnWithIdentifier:@"action"] dataCell] setWraps:YES];
   [[[tableView tableColumnWithIdentifier:@"object"] dataCell] setWraps:YES];
   [[[tableView tableColumnWithIdentifier:@"location"] dataCell] setWraps:YES];
   [[[tableView tableColumnWithIdentifier:@"source"] dataCell] setWraps:YES];
   [[[tableView tableColumnWithIdentifier:@"remark"] dataCell] setWraps:YES];
   

   SSEBDateFormatter *dateFormatter = [[[SSEBDateFormatter alloc] initWithDateFormat:[NSString stringWithFormat:@"%@:%@:%@",
      @"%Y", @"%m", @"%d"] allowNaturalLanguage:NO] autorelease];
   SSEBDateFormatter *timeFormatter = [[[SSEBDateFormatter alloc] initWithDateFormat:[NSString stringWithFormat:@"%@:%@:%@:%@",
      @"%H", @"%M", @"%S", @"%F"] allowNaturalLanguage:NO] autorelease];
   [[[tableView tableColumnWithIdentifier:@"beginDate"] dataCell] setFormatter:dateFormatter];
   [[[tableView tableColumnWithIdentifier:@"endDate"] dataCell] setFormatter:dateFormatter];
   [[[tableView tableColumnWithIdentifier:@"beginTime"] dataCell] setFormatter:timeFormatter];
   [[[tableView tableColumnWithIdentifier:@"endTime"] dataCell] setFormatter:timeFormatter];

   SSSourceFormatter *sourceFormatter = [[[SSSourceFormatter alloc] init] autorelease];
   [[[tableView tableColumnWithIdentifier:@"source"] dataCell] setFormatter:sourceFormatter];

   SSEBDurationFormatter *durationFormatter = [[[SSEBDurationFormatter alloc] init] autorelease];
   [[[tableView tableColumnWithIdentifier:@"duration"] dataCell] setFormatter:durationFormatter];
   
   [tableView setDrawsGrid:NO];
   [tableView setDrawsGrid:YES];
   
   //enumerate through the table columns and remove the ones that shouldn't be displayed
   enumerator = [[tableView tableColumns] objectEnumerator];
   id column;
   NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
   NSString *keyString;

   while (column = [enumerator nextObject]) {
      keyString = [NSString stringWithFormat:@"SSEBTable%@ColumnKey", [[column identifier] capitalizedString]]; //create a string for this columns preferences

      if(![defaults boolForKey:keyString]) {
         //the user wants to remove this column from the table
         [unusedTableColumns addObject:column];
         [tableView removeTableColumn:column];
      }
   }
   
   [tableView sizeLastColumnToFit];
   [tableView setAutosaveName:@"EBPanelTable"];
   [tableView setAutosaveTableColumns:YES];
}

- (void)updateTableDisplay:(NSNotification *)notification
{
   NSString *identifier;
   NSTableColumn *column;

   //get the identifier string
   switch([[notification object] tag]) {
      case preferenceETDisplayActorColumnTag:identifier = @"actor";
         break;
      case preferenceETDisplayActionColumnTag:identifier = @"action";
         break;
      case preferenceETDisplayObjectColumnTag:identifier = @"object";
         break;
      case preferenceETDisplayLocationColumnTag:identifier = @"location";
         break;
      case preferenceETDisplaySourceColumnTag:identifier = @"source";
         break;
      case preferenceETDisplayRemarkColumnTag:identifier = @"remark";
         break;
      case preferenceETDisplayBeginTimeColumnTag:identifier = @"beginTime";
         break;
      case preferenceETDisplayEndTimeColumnTag:identifier = @"endTime";
         break;
      case preferenceETDisplayBeginDateColumnTag:identifier = @"beginDate";
         break;
      case preferenceETDisplayEndDateColumnTag:identifier = @"endDate";
         break;
      case preferenceETDisplayXPosColumnTag:identifier = @"xPosition";
         break;
      case preferenceETDisplayLabelColumnTag:identifier = @"label";
         break;
      case preferenceETDisplayDurationColumnTag:identifier = @"duration";
         break;
      default:
         break;
   }

   //add or remove the tabel column
   if([[notification object] state]) {
      //we are adding the column
      column = [self unusedTableColumnWithIdentifier:identifier];
      NSLog(@"wanting to add %@", column);
      if(column) {
         NSLog(@"add %@", column);
         [tableView addTableColumn:column];
         [unusedTableColumns removeObjectIdenticalTo:column];
      }
   } else {
      //we are removing the collumn
      column = [tableView tableColumnWithIdentifier:identifier];
      NSLog(@"wanting to remove %@", column);
      if(column) {
         NSLog(@"remove %@", column);
         [unusedTableColumns addObject:column];
         [tableView removeTableColumn:column];
      }
   }

   [tableView sizeLastColumnToFit];
}

- (NSTableColumn *)unusedTableColumnWithIdentifier:(NSString *)string
{
   NSEnumerator *enumerator = [unusedTableColumns objectEnumerator];
   id anObject;

   while (anObject = [enumerator nextObject]) {
      if([[anObject identifier] isEqualToString:string]) {
         //we are holding the column
         return anObject;
      }
   }

   return nil;
}

- (NSMutableArray *)dataArray
{
   return dataArray;
}

- (void)setNeedsUpdate
{
   needsUpdate = YES;
}


- (void)windowDidUpdate:(NSNotification *)notification {
   //this is called each time the window updates, if something has changed
   //needsUpdate is set to YES elsewhere so we test it here and update as needed
   if(needsUpdate) {
      [self updateDataArray];
      needsUpdate = NO;
   }
}

- (void)reload
{
   [tableView reloadData];
}

- (void)updateDataArray
{
   [dataArray release];
   
   if(isUsing103OrLater && ![[searchField stringValue] isEqualToString:[NSString string]]) {
      //user is searching
      NSArray *itemArray = [[[searchField cell] searchMenuTemplate] itemArray];
      
      int i = 0;
      int searchTypeTag;
      while(i < [itemArray count]) {
         if([[itemArray objectAtIndex:i] state] == NSOnState) {
            //this is the search type we want
            searchTypeTag = [[itemArray objectAtIndex:i] tag];
            break;
         }      
         i++;
      }
      
      switch(searchTypeTag) {
         case SSEBSearchAllType:dataArray = [[[[NSDocumentController sharedDocumentController] currentDocument] allEventsContainingString:[searchField stringValue]] retain];
            break; 
         case SSEBSearchActorType:dataArray = [[[[NSDocumentController sharedDocumentController] currentDocument] allEventsWithActorContainingString:[searchField stringValue]] retain];
            break;
         case SSEBSearchActionType:dataArray = [[[[NSDocumentController sharedDocumentController] currentDocument] allEventsWithActionContainingString:[searchField stringValue]] retain];
            break;
         case SSEBSearchObjectType:dataArray = [[[[NSDocumentController sharedDocumentController] currentDocument] allEventsWithObjectContainingString:[searchField stringValue]] retain];
            break;
         case SSEBSearchSourceType:dataArray = [[[[NSDocumentController sharedDocumentController] currentDocument] allEventsWithSourceContainingString:[searchField stringValue]] retain];
            break;
         case SSEBSearchLocationType:dataArray = [[[[NSDocumentController sharedDocumentController] currentDocument] allEventsWithLocationContainingString:[searchField stringValue]] retain];
            break;
         case SSEBSearchRemarkType:dataArray = [[[[NSDocumentController sharedDocumentController] currentDocument] allEventsWithRemarkContainingString:[searchField stringValue]] retain];
            break;
         case SSEBSearchBeginDateType:dataArray = [[[[NSDocumentController sharedDocumentController] currentDocument] allEventsWithBeginDate:[searchField objectValue]] retain];
            break;
         case SSEBSearchBeginTimeType:dataArray = [[[[NSDocumentController sharedDocumentController] currentDocument] allEventsWithBeginTime:[searchField objectValue]] retain];
            break;
         case SSEBSearchEndDateType:dataArray = [[[[NSDocumentController sharedDocumentController] currentDocument] allEventsWithEndDate:[searchField objectValue]] retain];
            break;
         case SSEBSearchEndTimeType:dataArray = [[[[NSDocumentController sharedDocumentController] currentDocument] allEventsWithEndTime:[searchField objectValue]] retain];
            break;
         default:dataArray = [[NSMutableArray arrayWithArray:[[[NSDocumentController sharedDocumentController] currentDocument] eventArray]] retain];
            break;
      } 
      
   } else {
      dataArray = [[NSMutableArray arrayWithArray:[[[NSDocumentController sharedDocumentController] currentDocument] eventArray]] retain];
   }

   [self sortDataArray:self];
}

- (IBAction)sortDataArray:(id)sender
{
   switch([[sortTypePopup selectedItem] tag]) {
      case SSActionSortType:[[self dataArray] sortUsingSelector:@selector(compareByAction:)];
           break; 
      case SSObjectSortType:[[self dataArray] sortUsingSelector:@selector(compareByObject:)];
           break;
      case SSLocationSortType:[[self dataArray] sortUsingSelector:@selector(compareByLocation:)];
           break;
      case SSSourceSortType:[[self dataArray] sortUsingSelector:@selector(compareBySource:)];
         break;
      case SSBeginTimeSortType:[[self dataArray] sortUsingSelector:@selector(compareByBeginTime:)];
         break;
      case SSEndTimeSortType:[[self dataArray] sortUsingSelector:@selector(compareByEndTime:)];
         break;
      case SSXPositionSortType:[[self dataArray] sortUsingSelector:@selector(compareByXPosition:)];
         break;
      default:[[self dataArray] sortUsingSelector:@selector(compareByActor:)];
         break;
   }

   [self reload];
}

- (IBAction)performSearch:(id)sender
{
   [self updateDataArray];
}

- (void)searchTypeChanged:(NSMenuItem *)selectedItem
{
   [searchField setFormatter:nil];
   //set all of the items states to off
   NSArray *itemArray = [[[searchField cell] searchMenuTemplate] itemArray];
   int i = 0;
   while(i < [itemArray count]) {
      if([[itemArray objectAtIndex:i] tag] == [selectedItem tag]) {
         //set the selected item to on
         [[itemArray objectAtIndex:i] setState:NSOnState];
      } else {
         [[itemArray objectAtIndex:i] setState:NSOffState];
      }
      
      i++;
   }
   
   //set a formatter if needed
   if([selectedItem tag] == SSEBSearchBeginDateType || [selectedItem tag] == SSEBSearchEndDateType) {
      NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] initWithDateFormat:[NSString stringWithFormat:@"%@:%@:%@",
         @"%Y", @"%m", @"%d"] allowNaturalLanguage:NO] autorelease];
      [searchField setFormatter:dateFormatter];
   } else if([selectedItem tag] == SSEBSearchBeginTimeType || [selectedItem tag] == SSEBSearchEndTimeType) {
      NSDateFormatter *timeFormatter = [[[NSDateFormatter alloc] initWithDateFormat:[NSString stringWithFormat:@"%@:%@:%@:%@",
         @"%H", @"%M", @"%S", @"%F"] allowNaturalLanguage:NO] autorelease];
      [searchField setFormatter:timeFormatter];
   }
   
   [self updateDataArray];
}

//***********************************table view data source
- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
   return [[self dataArray] count];
}

- (id)tableView:(NSTableView *)aTableView
objectValueForTableColumn:(NSTableColumn *)aTableColumn
            row:(int)rowIndex
{
   NSString *identifier = [aTableColumn identifier];
   id record = [[self dataArray] objectAtIndex:rowIndex];

   if([identifier isEqualToString:@"beginDate"]) {
      return [record valueForKey:@"beginTime"];
   } else if([identifier isEqualToString:@"endDate"]) {
      return [record valueForKey:@"endTime"];
   } else if([identifier isEqualToString:@"duration"]) {
      return [NSNumber numberWithDouble:[[record endTime] timeIntervalSinceDate:[record beginTime]]];
   } else {
      //just return the value for identifier
      return [record valueForKey:identifier];
   }
}

- (void)tableView:(NSTableView *)aTableView
   setObjectValue:(id)anObject
   forTableColumn:(NSTableColumn *)aTableColumn
              row:(int)rowIndex
{
   NSString *identifier = [aTableColumn identifier];
   id record = [[self dataArray] objectAtIndex:rowIndex];

   if([identifier isEqualToString:@"beginTime"]) {
      [record takeValue:[self dateByCombiningDate:[record beginTime]
                                             time:anObject isEstimated:[anObject isEstimated]] forKey:@"beginTime"];
   } else if([identifier isEqualToString:@"beginDate"]) {
      [record takeValue:[self dateByCombiningDate:anObject
                                             time:[record beginTime] isEstimated:[anObject isEstimated]] forKey:@"beginTime"];
   } else if([identifier isEqualToString:@"endTime"]) {
      [record takeValue:[self dateByCombiningDate:[record endTime]
                                             time:anObject isEstimated:[anObject isEstimated]] forKey:@"endTime"];
   } else if([identifier isEqualToString:@"endDate"]) {
      [record takeValue:[self dateByCombiningDate:anObject
                                             time:[record endTime] isEstimated:[anObject isEstimated]] forKey:@"endTime"];
   } else if([identifier isEqualToString:@"duration"]) {
      SSChartDate *incrementedDate = [[[SSChartDate alloc] initWithTimeInterval:[anObject doubleValue] sinceDate:[record beginTime]] autorelease];
      [incrementedDate setIsEstimated:[[record endTime] isEstimated]];
      [record setEndTime:incrementedDate];
   } else {
      //standard value
      [record takeValue:anObject forKey:identifier];
   }

   if([identifier isEqualToString:@"xPosition"]) {
      //redisplay the main chart so that the EBs new position will be displayed
      [[[NSDocumentController sharedDocumentController] currentDocument] redisplay];
   }
}

- (void)tableViewSelectionDidChange:(NSNotification *)note
{
   //get the view to scroll to this object
   int rowIndex = [tableView selectedRow];
   if(rowIndex != -1) {
      [[[NSDocumentController sharedDocumentController] currentDocument] selectAndDisplayObject:[[[self dataArray] objectAtIndex:rowIndex] eventView]];
   }
}

- (NSTableView *)tableView
{
   return tableView;
}

//***********************************
- (SSChartDate *)dateByCombiningDate:(SSChartDate *)dateObject time:(SSChartDate *)timeObject isEstimated:(BOOL)est
{
   SSChartDate *finalDate;

   if(dateObject && timeObject) {
      //ther is a end date and time so joing them into the same date
      finalDate = [[[SSChartDate alloc] initWithString:[NSString stringWithFormat:@"%@/%@/%@/%@/%@/%@/%@", [dateObject descriptionWithCalendarFormat:@"%Y"],
         [dateObject descriptionWithCalendarFormat:@"%m"], [dateObject descriptionWithCalendarFormat:@"%d"], [timeObject descriptionWithCalendarFormat:@"%H"],
         [timeObject descriptionWithCalendarFormat:@"%M"], [timeObject descriptionWithCalendarFormat:@"%S"], [timeObject descriptionWithCalendarFormat:@"%F"]]
                                        calendarFormat:@"%Y/%m/%d/%H/%M/%S/%F" isEstimated:est] autorelease];
   } else {
      if(dateObject) {
         //there is a end date but no time
         finalDate = dateObject;
      } else {
         if(timeObject) {
            //there is a time but no date
            finalDate = timeObject;
         } else {
            //there is no time or date
            finalDate = [SSChartDate chartDateWithCalendarDate:[NSCalendarDate calendarDate] isEstimated:est];
         }
      }
   }
   
   return finalDate;
}


//***********************************

- (void)dealloc
{
   [[NSNotificationCenter defaultCenter] removeObserver:self];
   
   [dataArray release];
   [unusedTableColumns release];
   [super dealloc];
}

@end
